#ifndef RP2INSTANCE_H
#define RP2INSTANCE_H

#include "Rp2WindowApplication.h"

#include "Rp2BlendedTerrainEffect.h"
#include "Rp2WaterEffect.h"


namespace Rp2
{

class Instance : public WindowApplication 
{

RP2_DECLARE_INITIALIZE;
public:
	Instance();
	~Instance();

	static void Terminate();

	virtual void InitRenderStates();

	// Event callback
	virtual bool OnInitialize();
	virtual void OnTerminate();
	virtual void OnIdle();
	//virtual void OnDisplay();
	virtual bool OnKeyDown(unsigned char ucKey,int iXPos,int iYPos);

protected:
	// Scene object
	void CreateScene();	
	NodePtr m_spkScene;
	WireframeStatePtr m_spkWireframe;
	MaterialStatePtr m_spkMaterial;
	Culler m_kCuller;

	// Animation
    double m_dAnimTime, m_dAnimTimeDelta;
	TriMeshPtr m_spkSkinMesh;
	SkinningEffectPtr m_spkSkinEffect0, m_spkSkinEffect1;
	SKControllerPtr m_spkSKCtrl;

	// Lights effect
	void AttachLights();
	LightPtr m_aspkLight[8];

	// Shadow map
	void InitSM();
	CameraPtr m_LightCam;

	// Material test
	void CreateMaterialObj();

	// Flat floor
	void CreateFloor();
	TriMeshPtr m_spkFloor;

	// Height field 
    void CreateHeightField();
	TriMeshPtr m_spkHeightField;
	ImagePtr m_spkHeight;
	BlendedTerrainEffectPtr m_spkTerrainEffect;

	// Water effect
	void CreateWaterEffect();
	void CreateNormalMapFromHeightImage (const char* acImageName);
	WaterEffectPtr m_spkWaterEffect;
	ImagePtr m_spkNormalMap;

	// 3DS model
	void Create3DS(std::string& rkFilename);

	// .obj model
	void LoadObj(std::string& rkFilename);
	std::vector<TriMesh*> m_akMesh;

	// load .R1 scene
	void LoadR1(std::string& rkFilename);

    // Time information.
    bool m_bStopped;
    float m_fStopTime;

    // Wave information.
    float m_fWaveSpeedAmplitude;
    float m_fWaveHeightAmplitude;
    float m_fBumpSpeedAmplitude;
    float m_afWaveSpeed[4];
    float m_afWaveHeight[4];
    float m_afBumpSpeed[4];


	// Texture boards 
	void CreateGeometry();
	Particles* CreateParticles();
	Particles* m_pkParticles;
	// objects
	TriMeshPtr pkBoard0;
	TriMeshPtr pkBoard1;
	TriMeshPtr pkBoard2;
	TriMeshPtr* pkBoards;

	// avi recorder
	AVIGenerator	m_kAVIGenerator;
	BYTE*			m_pBits;	
	bool			m_bWritingAVI;


	// opengl framebuffer
	void RenderToTexture();
    CameraPtr m_spkScreenCamera;
    TriMeshPtr m_spkScenePolygon;
    ImagePtr m_spkSceneImage;
    Texture* m_pkSceneTarget;
    FrameBuffer* m_pkPBuffer;

	// debug
	bool m_bVsynOn;
	bool m_bDebugOn;
};

RP2_REGISTER_INITIALIZE(Instance);

}

#endif